﻿using System;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;
using System.Windows.Media;
using System.Text;

namespace SpriteSheetsCreator {
    #region String extender
    /// <summary>
    /// Extension of String class - add useful methods to string class
    /// </summary>
    public static class StringExtender {
        /// <summary>
        /// substring left content.
        /// Example: s="myContent" / count=2 / result="my"
        /// </summary>
        /// <param name="s"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static string subLeft(this string s, int count) {
            return s.Substring(0, count);
        }

        /// <summary>
        /// substring right content.
        /// Example: s="myContent" / count=2 / result="nt"
        /// </summary>
        /// <param name="s"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static string subRight(this string s, int count) {
            return s.Substring(s.Length - count, count);
        }

        /// <summary>
        /// substring by removing left content.
        /// Example: s="myContent" / count=2 / result="Content"
        /// </summary>
        /// <param name="s"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static string subRemoveLeft(this string s, int count) {
            return s.Substring(count, s.Length - count);
        }

        /// <summary>
        /// substring by removing right content.
        /// Example: s="myContent" / count=3 / result="myCont"
        /// </summary>
        /// <param name="s"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static string subRemoveRight(this string s, int count) {
            return s.Substring(0, s.Length - count);
        }

        /// <summary>
        /// uppercase only first character of string
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string uppercaseFirstChar(this string s) {
            if (s.isNullOrEmpty(true)) {
                return s;
            }
            char[] a = s.ToCharArray();
            a[0] = char.ToUpper(a[0]);
            return new string(a);
        }

        /// <summary>
        /// Return string or default value if null or empty
        /// </summary>
        /// <param name="s"></param>
        /// <param name="defaultValue"></param>
        /// <param name="ignoreSpaces"></param>
        /// <param name="ignoreCR"></param>
        /// <returns></returns>
        public static string toDefaultIfNull(this string s, string defaultValue = "", bool ignoreSpaces = false, bool ignoreCR = false) {
            if (s.isNullOrEmpty(ignoreSpaces, ignoreCR)) {
                return defaultValue;
            }
            return s;
        }

        /// <summary>
        /// return true if string is null or empty.
        /// </summary>
        /// <param name="s"></param>
        /// <param name="ignoreSpaces">if true, ignore spaces (return true if only spaces)</param>
        /// <param name="ignoreCR">if true, ignore carriage returns (\n) (return true if only carriage returns)</param>
        /// <returns></returns>
        public static bool isNullOrEmpty(this string s, bool ignoreSpaces = false, bool ignoreCR = false) {
            if (s == null) {
                return true;
            }
            string newS = "" + s;
            if (ignoreSpaces) {
                newS = newS.Replace(" ", "");
            }
            if (ignoreCR) {
                newS = newS.Replace("\n", "");
            }
            return string.IsNullOrEmpty(newS);
        }

        /// <summary>
        /// Return bool value from string.
        /// If parse doesn't work, return default value (false by default).
        /// Note: this works with "True", "true", "False", "false" or even "   True  " etc.
        /// </summary>
        public static bool toBool(this string s, bool defaultValue = false) {
            if (s.isNullOrEmpty()) return defaultValue;
            bool boolValue = defaultValue;
            bool.TryParse(s, out boolValue);
            return boolValue;
        }

        /// <summary>
        /// Return integer value from string.
        /// If parse doesn't work, return default value (0 by default).
        /// </summary>
        public static int toInteger(this string s, int defaultValue = 0) {
            if (s.isNullOrEmpty()) return defaultValue;
            int integerValue = defaultValue;
            int.TryParse(s, out integerValue);
            return integerValue;
        }

        /// <summary>
        /// Return long value from string.
        /// If parse doesn't work, return default value (0 by default).
        /// </summary>
        public static long toLong(this string s, long defaultValue = 0) {
            if (s.isNullOrEmpty()) return defaultValue;
            long longValue = defaultValue;
            long.TryParse(s, out longValue);
            return longValue;
        }

        /// <summary>
        /// Return true if string is an integer.
        /// </summary>
        public static bool isInteger(this string s) {
            Regex regularExpression = new Regex("^-[0-9]+$|^[0-9]+$");
            return regularExpression.Match(s).Success;
        }

        /// <summary>
        /// Return bool value from string.
        /// If parse doesn't work, return default value (false by default).
        /// Note: this works with "True", "true", "False", "false" or even "   True  " etc.
        /// </summary>
        public static bool? toNullableBool(this string s, bool? defaultValue = null) {
            bool? boolValue = defaultValue;
            try {
                boolValue = bool.Parse(s);
            }
            catch {
                boolValue = defaultValue;
            }
            return boolValue;
        }

        /// <summary>
        /// Return nullable integer value from string.
        /// If parse doesn't work, return default value (null by default).
        /// </summary>
        public static int? toNullableInteger(this string s, int? defaultValue = null) {
            int? integerValue;
            try {
                integerValue = int.Parse(s);
            }
            catch {
                integerValue = defaultValue;
            }
            return integerValue;
        }

        /// <summary>
        /// Return long value from string.
        /// If parse doesn't work, return default value (null by default).
        /// </summary>
        public static long? toNullableLong(this string s, long? defaultValue = null) {
            long? longValue;
            try {
                longValue = long.Parse(s);
            }
            catch {
                longValue = defaultValue;
            }
            return longValue;
        }

        public static string RemoveDiacriticsAndLower(this string text) {
            string result = text.ToLower().Replace('â', 'a');
            result = result.Replace('à', 'a');
            result = result.Replace('é', 'e');
            result = result.Replace('è', 'e');
            result = result.Replace('ê', 'e');
            result = result.Replace('î', 'i');

            return result;
        }
    }
    #endregion

    #region List extender
    /// <summary>
    /// Extension of ArrayList class - add useful methods to ArrayList class
    /// </summary>
    public static class ListExtender {
        /// <summary>
        /// Determines whether a collection is null or has no elements 
        /// </summary>
        /// <typeparam name="T">The item type.</typeparam>
        /// <param name="al">The list to evaluate.</param>
        /// <returns>
        /// <c>true</c> if this list is null or empty; otherwise, <c>false</c>.
        /// </returns>
        public static bool isNullOrEmpty(this List<object> al) {
            return al == null || al.Count == 0;
        }
    }
    #endregion

    #region DateTime extender
    public static class DateTimeExtender {
        /// <summary>
        /// Return the first of the date month (i.e. date param "12. June 2011" will return "1st June 2011")
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime getMonthFirstDate(this DateTime dt) {
            return new DateTime(dt.Year, dt.Month, 1);
        }

        /// <summary>
        /// Return the last day in the date month (i.e. date param "12. June 2011" will return "30. June 2011")
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime getMonthLastDate(this DateTime dt) {
            return new DateTime(dt.Year, dt.Month, DateTime.DaysInMonth(dt.Year, dt.Month));
        }

        /// <summary>
        /// Return shortDate + " " + shortTime
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static string toShortDateAndTimeString(this DateTime dt) {
            return dt.ToShortDateString() + " " + dt.ToShortTimeString();
        }
    }
    #endregion

    #region IEnumerable extender
    public static class IEnumerableExtender {
        public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
            HashSet<TKey> seenKeys = new HashSet<TKey>();
            foreach (TSource element in source) {
                if (seenKeys.Add(keySelector(element))) {
                    yield return element;
                }
            }
        }
    }
    #endregion

    #region Color extenders
    static class ColorExtender {
        /// <summary>
        /// Convert hexa #RRGGBB string to Color
        /// </summary>
        /// <param name="hexRgb"></param>
        /// <returns></returns>
        public static Color ToColorFromRgb(this string hexRgb) {
            uint argb = UInt32.Parse(hexRgb.Replace("#", "FF"), NumberStyles.HexNumber);
            return argb.ToColor();
        }

        /// <summary>
        /// <summary>
        /// Convert hexa #AARRGGBB string to Color
        /// </summary>
        /// <param name="hexRgb"></param>
        /// <returns></returns>
        /// </summary>
        /// <param name="hexArgb"></param>
        /// <returns></returns>
        public static Color ToColorFromArgb(this string hexArgb) {
            uint argb = UInt32.Parse(hexArgb.Replace("#", ""), NumberStyles.HexNumber);
            return argb.ToColor();
        }

        /// <summary>
        /// Convert Uint ARGB to Color
        /// </summary>
        /// <param name="argb"></param>
        /// <returns></returns>
        public static Color ToColor(this uint argb) {
            return Color.FromArgb((byte)((argb & -16777216) >> 0x18),
                                  (byte)((argb & 0xff0000) >> 0x10),
                                  (byte)((argb & 0xff00) >> 8),
                                  (byte)(argb & 0xff));
        }
    }
    #endregion
}
